// Copyright (c) 2022 by Duguang.IO Inc. All Rights Reserved.
// Author: Ethan Liu
// Date: 2022-05-18 11:24:06

package poller

import (
	"context"
	"fmt"
	"runtime/debug"
	"sync"

	"jianmu-worker-kube/client"
	"jianmu-worker-kube/engine"

	logger "jianmu-worker-kube/logging"
)

var noContext = context.Background()

// Poller 从服务器拉取任务执行
type Poller struct {
	Client      client.Client
	Filter      *client.Filter
	NodeName    string
	NameSpace   string
	DataDir     string
	HelperImage string
	// 分发任务执行
	Dispatch func(context.Context, *engine.Unit) error
}

// Poll 开启n个连接并发获取任务
func (p *Poller) Poll(ctx context.Context, n int) {
	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func(i int) {
			for {
				select {
				case <-ctx.Done():
					wg.Done()
					return
				default:
					p.poll(ctx, i+1)
				}
			}
		}(i)
	}

	wg.Wait()
}

// poll 拉取任务并分发执行
func (p *Poller) poll(ctx context.Context, thread int) error {
	defer func() {
		if err := recover(); err != nil {
			logger.FromContext(ctx).Errorf("panic in poller err: %v", err)
			stackStr := string(debug.Stack())
			fmt.Println(stackStr)
		}
	}()

	log := logger.FromContext(ctx).WithField("thread", thread)
	log.WithField("thread", thread).Debug("poller: request runner from ci server")

	valueCtx := context.WithValue(ctx, "nodeName", p.NodeName)
	valueCtx = context.WithValue(valueCtx, "nameSpace", p.NameSpace)
	valueCtx = context.WithValue(valueCtx, "helperImage", p.HelperImage)

	unit, err := p.Client.Request(valueCtx, p.Filter)

	unit.DataDir = p.DataDir

	if err == context.Canceled || err == context.DeadlineExceeded {
		log.WithError(err).Trace("poller: no runner returned")
		return nil
	}
	if err != nil {
		log.WithError(err).Error("poller: cannot request runner")
		return err
	}

	/*	if unit == nil || unit.PodSpec.Name == "" {
		return nil
	}*/

	return p.Dispatch(
		logger.WithLogger(noContext, log), unit)
}
